package chatserver_01;

import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.kryonet.Server;
import com.esotericsoftware.minlog.Log;
import java.awt.AWTException;
import java.awt.Font;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import network_01.Network;
import network_01.ResourceManager;

public class ChatServer {

  private Server server;
  private String hostName = "server";
  private SystemTray tray = SystemTray.getSystemTray();
  private TrayIcon trayIcon = new TrayIcon(ResourceManager.createImage(getClass(), "resources/49.gif"), "Chat Server");

  public ChatServer() throws IOException {
    
    this.server = new Server() {

      @Override
      protected Connection newConnection() {
        return new ChatServer.ChatConnection();
      }
    };
    Network.register(this.server);
    this.server.addListener(new ServerListener());
    this.server.bind(54555);
    this.server.start();
    PopupMenu trayPopupMenu = new PopupMenu();
    MenuItem stop = new MenuItem();
    stop.setLabel("Stop server");
    stop.setFont(new Font("Tahoma", 0, 11));
    stop.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent evt) {
        ChatServer.this.server.stop();
        ChatServer.this.tray.remove(ChatServer.this.trayIcon);
      }
    });
    trayPopupMenu.add(stop);
    this.trayIcon.setPopupMenu(trayPopupMenu);
    this.trayIcon.setImageAutoSize(true);
    try {
      this.tray.add(this.trayIcon);
    } catch (AWTException ex) {
      Logger.getLogger(ChatServer.class.getName()).log(Level.SEVERE, null, ex);
    }
  }

  private void sendRecipientList() {
    Network.RecipientList nameList = new Network.RecipientList();
    Connection[] connections = this.server.getConnections();
    String[] nm = new String[connections.length];
    int i = 0;
    for (int n = connections.length; i < n; i++) {
      ChatConnection connection = (ChatConnection) connections[i];
      nm[i] = connection.name;
    }
    nameList.names = nm;
    this.server.sendToAllTCP(nameList);
  }

  private int getConnectionID(String name) {
    Connection[] connections = this.server.getConnections();
    int i = 0;
    for (int n = connections.length; i < n; i++) {
      ChatConnection connection = (ChatConnection) connections[i];
      if (name.equals(connection.name)) {
        return connection.getID();
      }
    }
    return -1;
  }

  public static void main(String[] args)
          throws IOException {
    Log.set(2);
    new ChatServer();
  }

  private class ChatConnection extends Connection {

    public String name;

    private ChatConnection() {
    }
  }

  private class ServerListener extends Listener {

    private ServerListener() {
    }

    @Override
    public void received(Connection c, Object object) {
      ChatServer.ChatConnection connection = (ChatServer.ChatConnection) c;

      if ((object instanceof Network.RegisterName)) {
        if (connection.name != null) {
          return;
        }
        String name = ((Network.RegisterName) object).name;
        if (name == null) {
          return;
        }
        if (name.length() == 0) {
          return;
        }
        if (ChatServer.this.getConnectionID(name) != -1) {
          Network.ChatMessage cm = new Network.ChatMessage();
          cm.text = ("The name \"" + name + "\" is already in use.");
          cm.style = Network.getDefaultStyle();
          cm.recipient = name;
          cm.origin = ChatServer.this.hostName;
          ChatServer.this.server.sendToTCP(connection.getID(), cm);
          connection.close();
          return;
        }
        connection.name = name;
        Network.ChatMessage cm = new Network.ChatMessage();
        cm.text = (name + " connected.");
        cm.style = Network.getDefaultStyle();
        cm.recipient = "  All  ";
        cm.origin = ChatServer.this.hostName;
        ChatServer.this.server.sendToAllTCP(cm);
        ChatServer.this.sendRecipientList();
        return;
      }

      if ((object instanceof Network.ChatMessage)) {
        Network.ChatMessage cm = (Network.ChatMessage) object;
        if (cm.text.length() == 0) {
          return;
        }
        cm.text = (connection.name + ": " + cm.text);
        if (cm.recipient.equals("  All  ")) {
          ChatServer.this.server.sendToAllTCP(cm);
        } else {
          ChatServer.this.server.sendToTCP(ChatServer.this.getConnectionID(cm.recipient), cm);
          ChatServer.this.server.sendToTCP(ChatServer.this.getConnectionID(cm.origin), cm);
        }
        return;
      }
    }

    @Override
    public void disconnected(Connection c) {
      ChatServer.ChatConnection connection = (ChatServer.ChatConnection) c;
      if (connection.name == null) {
        return;
      }

      Network.ChatMessage cm = new Network.ChatMessage();
      cm.text = (connection.name + " disconnected.");
      cm.style = Network.getDefaultStyle();
      cm.recipient = "  All  ";
      ChatServer.this.server.sendToAllTCP(cm);
      ChatServer.this.sendRecipientList();
    }
  }
}